package com.ck.express.tcp


import TcpMessageDecoder
import android.content.Context
import android.content.SharedPreferences
import android.util.Log
import com.ck.express.activity.LoginActivity
import io.netty.bootstrap.Bootstrap
import io.netty.buffer.Unpooled
import io.netty.channel.Channel
import io.netty.channel.ChannelInitializer
import io.netty.channel.ChannelOption
import io.netty.channel.EventLoopGroup
import io.netty.channel.nio.NioEventLoopGroup
import io.netty.channel.socket.SocketChannel
import io.netty.channel.socket.nio.NioSocketChannel
import kotlinx.coroutines.CompletableDeferred
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.delay
import kotlinx.coroutines.sync.Mutex
import kotlinx.coroutines.sync.withLock
import kotlinx.coroutines.withContext
import java.io.IOException

/**
 * 优化版 TCP 客户端：支持协程友好调用、并发安全、资源管理更健壮
 */
object TcpOperationDownClient {
    private var host: String = "192.1.68.1.10" // 默认值，会在init中覆盖
    private var port: Int = 10007 // 默认值，会在init中覆盖
    private lateinit var sharedPreferences: SharedPreferences

    private var group: EventLoopGroup = NioEventLoopGroup()
    private var channel: Channel? = null

    private val mutex = Mutex() // 保证连接串行化
    private var responseDeferred: CompletableDeferred<String>? = null

    /**
     * 初始化TCP客户端，从SharedPreferences加载配置
     */
    fun init(context: Context) {
        sharedPreferences = context.getSharedPreferences("ip_config", Context.MODE_PRIVATE)
        loadLoginConfig()
    }

    /**
     * 从SharedPreferences加载登录服务器配置
     */
    private fun loadLoginConfig() {
        host =
            sharedPreferences.getString(LoginActivity.KEY_LOGIN_IP, "192.1.68.1.10") ?: "192.1.68.1.10"
        port = sharedPreferences.getString(LoginActivity.KEY_LOGIN_PORT, "10007")?.toIntOrNull()
            ?: 10007
        Log.i("TcpOperationDownClient", "加载服务器配置: $host:$port")
    }

    /**
     * 动态更新配置
     */
    fun configure(host: String, port: Int) {
        TcpOperationDownClient.host = host
        TcpOperationDownClient.port = port
        Log.i("TcpOperationDownClient", "更新服务器配置: $host:$port")
    }

    suspend fun connect(): Boolean = withContext(Dispatchers.IO) {
        mutex.withLock {
            if (channel?.isActive == true) return@withContext true

            try {
                val bootstrap = Bootstrap()
                bootstrap.group(group)
                    .channel(NioSocketChannel::class.java)
                    .option(ChannelOption.TCP_NODELAY, true)
                    .option(ChannelOption.CONNECT_TIMEOUT_MILLIS, 5000)
                    .handler(object : ChannelInitializer<SocketChannel>() {
                        override fun initChannel(ch: SocketChannel) {
                            Log.i("TcpOperationDownClient", "初始化pipeline")
                            ch.pipeline().addLast(TcpMessageEncoder())
                            ch.pipeline().addLast(TcpMessageDecoder())
                            ch.pipeline().addLast(DownClientInboundHandler())
                        }
                    })

                Log.i("TcpOperationDownClient", "尝试连接服务器: $host:$port")
                val ch = bootstrap.connect(host, port).sync().channel()
                Log.i("TcpOperationDownClient", "连接成功")
                channel = ch
                true
            } catch (e: Exception) {
                e.printStackTrace()
                channel = null
                false
            }
        }
    }

    suspend fun send(jsonBody: String): String = withContext(Dispatchers.IO) {
        repeat(3) { attempt ->
            try {
                if (!connect()) throw IOException("TCP 连接失败")

                val deferred = CompletableDeferred<String>()
                responseDeferred = deferred

                // 构建带长度头的完整消息
                val lengthHeader = String.format("%08d", jsonBody.toByteArray(charset("GBK")).size)
                val fullMessage = lengthHeader + jsonBody
                Log.i("TcpOperationDownClient", "发送完整请求:${fullMessage}")
                // 发送完整消息
                channel?.writeAndFlush(Unpooled.copiedBuffer(fullMessage, charset("GBK")))?.sync()

                // 直接获取解码器处理后的纯JSON字符串
                val response = deferred.await()
                return@withContext response

            } catch (e: Exception) {
                if (attempt == 2) throw e
                close()
                delay(500)
            }
        }
        throw IOException("发送失败")
    }

    fun receive(msg: String) {
        responseDeferred?.complete(msg)
        responseDeferred = null
    }

    fun close() {
        channel?.close()
        channel = null
    }

    fun shutdown() {
        close()
        group.shutdownGracefully()
    }
}